Drawing and Hit-Testing Shapes
Drawing and hit-testing are common actions you may perform with any kind of shape. The most basic QuickDraw GX drawing function isGXDrawShape
, although there are other functions for drawing specific types of shapes. OnlyGXDrawShape
is described here.The functions you use for hit-testing are
GXHitTestShape
,GXHitTestPicture
,GXHitTestLayout
, andGXHitTestDevice
. OnlyGXHitTestShape
is described here.Drawing Shapes
Drawing a shape is the logical conclusion to creating it and setting its properties. Drawing occurs in the view port or view ports specified in the transform object associated with the shape. Drawing takes into account all the information in the shape's transform, ink, style, and shape objects.What it means to draw a specific type of shape and how changing the information in a shape alters its drawn appearance is described, along with each type of shape, in Inside Macintosh: QuickDraw GX Graphics and Inside Macintosh: QuickDraw GX Typography. Furthermore, for many shape types, QuickDraw GX provides specialized drawing functions, such as
GXDrawLine
andGXDrawGlyphs
--described in those books--that allow you to create, draw, and dispose of an object with a single call.At its most basic, though, creating and drawing a shape is as simple as the following listing for creating and drawing a path shape shows:
gxShape myShape; /* allocate the variable */ myShape = GXNewShape(gxPathType); /* create the shape */ . . /* set its properties */ . GXDrawShape(myShape); /* draw it */TheGXDrawShape
function is described on page 2-84.Hit-Testing Shapes
Hit-testing converts a coordinate location to a shape-geometry location. It can give you feedback on user actions involving a shape you have drawn. For example, you use hit-testing to select a shape the user has clicked the mouse over, to select a point within a shape, or to position the insertion point and draw the caret within the text of a typographic shape.QuickDraw GX provides a general hit-testing function for all shapes, plus specialized functions for hit-testing picture shapes, layout shapes, and pixels on a display device:
When you hit-test a shape with
GXHitTestShape
tests a point in local space against a shape's geometry. The test tells you which part of a shape's geometry--out of a specified set of parts--corresponds (within the tolerance) to the point you are testing with. TheGXHitTestShape
function is described in this chapter.GXHitTestPicture
tests a point in local space against a picture shape. The test tells you which part of which shape within the picture corresponds (within the tolerance) to the point you are testing against (subject to the constraints on shape overlap and hierarchy that you provide). TheGXHitTestPicture
function is described in the picture shapes chapter of Inside Macintosh: QuickDraw GX Graphics.GXHitTestLayout
tests a point in local space against the text of a layout shape. The test tells you, along with other information, which character in the text corresponds to the point. Note that you useGXHitTestShape
to test typographic shapes other than layout shapes, and you can use it for layout shapes also; it gives different kinds of information fromGXHitTestLayout
. TheGXHitTestLayout
function is described in the layout carets, highlighting, and hit-testing chapter of Inside Macintosh: QuickDraw GX Typography.GXHitTestDevice
tests a pixel (a point in device space) against a shape's geometry. The test tells you whether or not any part of the shape's geometry is within a certain distance of the pixel. TheGXHitTestDevice
function is described in the chapter "View-Related Objects" in this book.
GXHitTestShape
, you must first set up the shape parts mask and the tolerance, two components of the hit-test parameters property of a shape's transform object. You pass that information toGXHitTestShape
, and QuickDraw GX returns information in the hit-test info structure.The tolerance is a distance (in units of geometry space), and it defines a circular area centered on the hit point. Any part that falls within that area is considered to correspond to the hit point.
Shape Parts
When you useGXHitTestShape
, it returns one or more shape parts, which specify the parts of the shape's geometry corresponding to the hit point. The parts of a shape's geometry for which you can hit-test depend on the kind of shape. The shape parts that you can test for are defined in the gxShapeParts enumeration. Before callingGXHitTestShape
, you set up, in the transform object, a mask of all the shape parts that you want to test for.GXHitTestShape
can test only for parts that you specify in the shape parts mask. These are the possible values to put into the mask:
enum gxShapeParts { /* (in order of evaluation) */ gxNoPart = 0, gxBoundsPart = 0x0001, gxGeometryPart = 0x0002, gxPenPart = 0x0004, gxCornerPointPart = 0x0008, gxControlPointPart = 0x0010, gxEdgePart = 0x0020, gxJoinPart = 0x0040, gxStartCapPart = 0x0080, gxEndCapPart = 0x0100, gxDashPart = 0x0200, gxPatternPart = 0x0400, gxGlyphBoundsPart = gxJoinPart, gxGlyphFirstPart = gxStartCapPart, gxGlyphLastPart = gxEndCapPart, gxSideBearingPart = gxDashPart, gxAnyPart = gxBoundsPart | gxGeometryPart | gxPenPart | gxCornerPointPart | gxControlPointPart | gxEdgePart | gxJoinPart | gxStartCapPart | gxEndCapPart | gxDashPart | gxPatternPart } ; typedef long gxShapePart;These values are described in more detail in the chapter "Transform Objects" in this book. Note that values specifying join, cap, and dash parts in geometric shapes are used in typographic shapes to specify various glyph parts. Note also that you can specify no parts or all parts in the mask. You decide which shape parts are appropriate for your needs.Hit-Test Info Structure
When you callGXHitTestShape
, it returns some information as a function result and other information in a hit-test info structure. The first three fields of the hit-test info structure give all the relevant information about the hit:
struct gxHitTestInfo { gxShapePart what; long index; Fixed distance; gxShape which; gxShape containerPicture; long containerIndex; long totalIndex; };Thewhat
field tells you which shape parts out of those specified in your mask were hit, if any. It is identical to theGXHitTestShape
function result.The
index
field tells you the index number of the point in the geometry that is closest to the hit point.The
distance
field tells you how far, in geometry coordinates, the hit point is from the first shape part that was hit.GXHitTestShape
analyzes shape parts in a specific order--the order listed in the gxShapeParts enumeration. By carefully specifying shape parts, you can useGXHitTestShape
to obtain specific distance information for a given part. For example, if you are hit-testing a line like that shown in Figure 2-5 on page 2-21, you can determine the distance from the hit point to the pen if you exclude both bounds and geometry from the test.The remaining fields in the hit-test info structure are not used by
GXHitTestShape
.Hit-Testing Example
Listing 2-2 uses hit-testing to determine whether a point (aPoint
) is contained in the geometry that represents a shape (gShape
). The code sets up a shape-part mask (mask
) specifying that only the geometry it to be tested for, and calls the GXSetShapeHitTest function to assign the mask, plus a tolerance of zero, to the shape's transform.Listing 2-2 Hit-testing a line
gxShape pointShape; gxPoint aPoint = {ff(50), ff(51)}; gxShapePart mask = gxGeometryPart; gxShapePart resultMask; gxHitTestInfo resultInfo; pointShape = GXNewPoint(&aPoint); GXSetShapeHitTest(gShape, mask, ff(0)); resultMask = GXHitTestShape(gShape, &aPoint, &resultInfo); GXDisposeShape(pointShape);The function result from GXHitTestShape tells which part of the shape was hit. Because only one part (gxGeometryPart) is specified and tolerance is 0, a successful hit is possible only ifaPoint
is actually within the geometry of the shape.In the event of a successful hit,
GXHitTestShape
also fills in agxHitTestInfo
structure (resultInfo
parameter) that contains additional information about the hit.The
gxHitTestInfo
structure is described on page 2-50. TheGXHitTestShape
function is described on page 2-86. Because the shape parts to test against are specified
in a shape's transform object, the list of defined QuickDraw GX shape parts, and theGXSetShapeHitTest
function, are described in the chapter "Transform Objects" in
this book.